package it.hive.mediaplayer;

import it.hive.mediaplayer.beans.impl.Traccia;
import it.hive.mediaplayer.listeners.MediaPlayerBufferListener;
import it.hive.mediaplayer.listeners.MediaPlayerPlayTimeListener;
import it.hive.mediaplayer.properties.MediaPlayerProperties;
import it.hive.mediaplayer.task.loader.MediaLoader;

import java.util.concurrent.ExecutionException;

import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.util.Duration;

public class MediaPlayerController {
	private Duration pauseTime;
	private volatile MediaPlayer mediaPlayer;
	private static MediaPlayerController istanza;
	private Traccia currentTrack;
	private MediaPlayerPlayTimeListener progressListener;
	private MediaPlayerBufferListener bufferListener;

	/* ############################################################################# */
	private MediaPlayerController() {
		MediaPlayerProperties.onPlaying.set(false);
		MediaPlayerProperties.onBuffering.set(false);
		MediaPlayerProperties.volumeProperty.set(0.2);
		MediaPlayerProperties.playBufferProperty.set(-1);
	};

	/* ############################################################################# */

	public static MediaPlayerController getMediaPlayerController() {
		if (istanza == null) {
			istanza = new MediaPlayerController();
		}
		return istanza;
	}

	public Traccia getCurrentTrack() {
		return currentTrack;
	}

	/**
	 * Istanzia ed avvia il MediaPlayer
	 * 
	 * @param t
	 */
	public void play(Traccia t) {
		istanziaMediaPlayer(t);
		avvia();
	}

	public synchronized MediaPlayer getMediaPlayer() {
		return mediaPlayer;
	}

	public void stop() {
		if (mediaPlayer != null && mediaPlayer.getStatus() != MediaPlayer.Status.DISPOSED) {
			if (mediaPlayer.getStatus() != MediaPlayer.Status.STOPPED) {
				MediaPlayerProperties.playTimeProgress.unbind();
				MediaPlayerProperties.playTimeProgress.set("M2O Reloaded Download & Play");
				MediaPlayerProperties.onPlaying.set(false);
				mediaPlayer.stop();
			}
		}
	}

	public void seek(double d) {
		if (mediaPlayer != null) {
			mediaPlayer.seek(mediaPlayer.getTotalDuration().multiply(d));
		}
	}

	public void pause() {
		pauseTime = mediaPlayer.getCurrentTime();
		String labelText = getCurrentTrack() != null ? "In pausa: " + getCurrentTrack().getTrackName() : "";
		MediaPlayerProperties.playTimeProgress.unbind();
		MediaPlayerProperties.playTimeProgress.set(labelText);
		MediaPlayerProperties.onPlaying.set(false);
		mediaPlayer.pause();
	}

	public void setVolume(double value) {
		if (mediaPlayer != null) {
			mediaPlayer.setVolume(value);
		}
	}

	/* ############################################################################# */

	private void istanziaMediaPlayer(Traccia traccia) {
		if (currentTrack != null && traccia != null) {
			if (currentTrack.equals(traccia)) {
				if (progressListener != null) {
					MediaPlayerProperties.playTimeProgress.bind(progressListener.getPlayTimeProgress());
				}
				return;
			}
		}
		currentTrack = traccia;
		if (mediaPlayer != null) {
			stop();
			mediaPlayer.dispose();
			mediaPlayer = null;
			progressListener = null;
			bufferListener = null;
		}
		Media media;
		try {
			media = new MediaLoader(traccia.getUrl()).get();
		} catch (InterruptedException | ExecutionException e) {
			media = null;
			System.out.println(e.getCause());
			this.stop();
		}
		if (media != null) {
			mediaPlayer = new MediaPlayer(media);
			progressListener = new MediaPlayerPlayTimeListener(mediaPlayer, traccia.getNomeTraccia());
			bufferListener = new MediaPlayerBufferListener(mediaPlayer);
			mediaPlayer.setAudioSpectrumNumBands(4);
			mediaPlayer.setAudioSpectrumInterval(0.05);
			//mediaPlayer.setAudioSpectrumListener(new AudioVisualizer());
			bindingProperties();
		}
	}

	/**
	 * Avvia la riproduzione
	 */
	private void avvia() {
		if (mediaPlayer != null) {
			switch (mediaPlayer.getStatus()) {
			case PAUSED:
				mediaPlayer.setStartTime(pauseTime);
				play();
				break;
			case STOPPED:
				mediaPlayer.setStartTime(Duration.ZERO);
				play();
			case UNKNOWN:
				play();
			default:
				break;
			}
		}
	}

	private void bindingProperties() {
		mediaPlayer.volumeProperty().bind(MediaPlayerProperties.volumeProperty);
		MediaPlayerProperties.playProgress.bind(progressListener.getPlayProgress());
		MediaPlayerProperties.playBufferProperty.bind(bufferListener.getBufferProgress());
		MediaPlayerProperties.onBuffering.bind(bufferListener.isOnBuffering());
		MediaPlayerProperties.playTimeProgress.bind(progressListener.getPlayTimeProgress());
	}

	/**
	 * Esegue il metodo play in un altro thread
	 */
	private void play() {
		MediaPlayerProperties.onPlaying.set(true);
		MediaPlayerProperties.tracciaInRiproduzione.set(currentTrack);
		new Thread(new Runnable() {
			@Override
			public void run() {
				mediaPlayer.play();
			}
		}).start();
	}

}
